package client

import (
	"context"
	"gogame/lib"
	"gogame/logger"
	"gogame/pb"
	"gogame/server/rpcx/param"
	"net/url"
	"strings"
	"sync"
)

// Selector 服务选择器
type Selector struct {
	sync.RWMutex
	client                 *RpcXClient
	serverAddressList      []string             // server地址列表
	serverAddress2Metadata map[string]*metadata // server地址对应的元数据
}

type metadata struct {
	name   string
	listen string
}

func NewSelector(client *RpcXClient) *Selector {
	return &Selector{
		client:                 client,
		serverAddressList:      make([]string, 0),
		serverAddress2Metadata: make(map[string]*metadata),
	}
}

// Select 选择服务
func (s *Selector) Select(ctx context.Context, servicePath, serviceMethod string, request any) string {
	var workerUrl string
	_request, ok := request.(*pb.ApiRequest)
	if ok {
		workerUrl = _request.WorkerUrl
		return workerUrl
	}

	_request2, ok2 := request.(*param.ClientArgs)
	if ok2 {
		workerUrl = _request2.WorkerUrl
		return workerUrl
	}

	// 随机一个
	for _, url := range s.serverAddressList {
		return url
	}

	return workerUrl
}

// RandWorkerUrl 随机一个workerUrl
func (s *Selector) RandWorkerUrl() string {
	_sLen := len(s.serverAddressList)
	// 服务不存在
	if _sLen == 0 {
		return ""
	}

	s.RLock()
	defer s.RUnlock()
	if _sLen == 1 {
		return s.serverAddressList[0]
	} else {
		_randIdx := lib.Rand.RandInt(0, _sLen)
		return s.serverAddressList[_randIdx]
	}
}

// DelServer 删除服务
func (s *Selector) DelServer(serverUrl string) {
	//logger.Print("DelServer  删除的的key-->%v", serverUrl)
	//logger.Print("DelServer  更新前-->%v", s.serverAddressList)
	s.Lock()
	defer s.Unlock()

	delete(s.serverAddress2Metadata, serverUrl)

	_newServerAddressList := make([]string, 0)
	for url, _ := range s.serverAddress2Metadata {
		_newServerAddressList = append(_newServerAddressList, url)
	}
	s.serverAddressList = _newServerAddressList
	//logger.Print("DelServer  更新后-->%v", s.serverAddressList)

}

// HasServer 服务是否存在
func (s *Selector) HasServer(serverUrl string) bool {
	_, ok := s.serverAddress2Metadata[serverUrl]

	return ok
}

// UpdateServer 更新服务
func (s *Selector) UpdateServer(servers map[string]string) {
	//logger.Print("updateServer  更新的servers-->%v", servers)
	//logger.Print("updateServer  更新前-->%v", s.serverAddressList)
	s.Lock()
	defer s.Unlock()

	_newServerAddressList := make([]string, 0)
	_newServerAddress2Metadata := make(map[string]*metadata)
	for serverAddress, v := range servers {
		_newServerAddressList = append(_newServerAddressList, serverAddress)

		// 解析服务元数据
		_metaData := parseMetadata(v)
		_newServerAddress2Metadata[serverAddress] = _metaData

		// 新服务注册别名
		_tag := s.client.Address
		// cmdClient不注册
		if strings.Contains(_tag, "cmd") {
			continue
		}
		_, ok := s.serverAddress2Metadata[serverAddress]
		if !ok {
			go func(serverAddress string) {
				s.client.RpcClient.Go(
					context.Background(),
					"ClientRegisterTag",
					&param.ClientArgs{
						Tag:       _tag,
						WorkerUrl: serverAddress,
					},
					&param.ClientRes{},
					nil,
				)
				logger.Print("注册rpcXClient别名【%s】到worker【%s】", _tag, serverAddress)
			}(serverAddress)
		}
	}

	s.serverAddressList = _newServerAddressList
	s.serverAddress2Metadata = _newServerAddress2Metadata

	//logger.Print("updateServer  更新后-->%v", s.serverAddressList)

}

// 解析服务元数据
func parseMetadata(data string) *metadata {
	urlValues, _ := url.ParseQuery(data)

	if urlValues == nil {
		return nil
	}

	return &metadata{
		name:   urlValues.Get("name"),
		listen: urlValues.Get("listen"),
	}
}
